import sys, os, re, urllib2, json
#PROJECT - tvrenamer by Brad Russell and Son Nguyen

#Settings
FORMAT = '{show} [{season}x{episode:02d}] {title}.{filetype}'
FILETYPES = '[avi, mp4, mkv]'
API_URL = 'http://sonng.es:8080/tv/search/{tvseries}'

class TV:
	def __init__(self, path):
		self.path = path
		self.series = ""
		self.season = 0
		self.rawEpisodes = []
		self.finalTitles = {}
		self.parsedEpisodes = {}
		self.episodeTitles = {}
		self.data = ""

	def GetEpisodes(self):
		"""Grabs supported video files from target folder and constructs a list of raw episode names."""
		if not os.path.exists(self.path):
			print 'Error: Target folder does not exist'
			sys.exit(1)
		for episode in os.listdir(self.path):
			if episode[-3:] in FILETYPES:
				self.rawEpisodes.append(episode)
			else:
				pass

	def ParseEpisodes(self):
		"""Parses raw episodes and retrieves episode numbers. ParsedEpisodes dictionary is then constructed
		with episode number and original episode name. Known formats: S01E01, 1x01, 101."""
		reg = '([Ss]\d{2}[Ee]\d{2}|\d{1,2}x\d{2}|\.\d{3}\.)'
		if len(self.rawEpisodes) == 0:
			raise NameError('Error: No video files found in target folder')
			if __name__ == "__main__":
				sys.exit(1)
		for episode in self.rawEpisodes:
			try:
				number = re.search(reg, episode).group()
				number = int(number[-2:])
				self.parsedEpisodes[number] = episode
			except AttributeError:
				print 'Regex Error:', episode, '(Unknown format)'
				pass

	def GetSeriesData(self):
		"""Parses series name and season number from folder structure, i.e. ../<Series>/<Season #>/.
		Series name is then sent to Son's API where series data is returned in JSON format."""
		splitter = ""
		opener = urllib2.build_opener()
		if '\\' in self.path:
			splitter = '\\'
		else:
			splitter = '/'
		raw = self.path.split(splitter)
		self.series = raw[-2]
		self.season = int(raw[-1][-1:])
		safeSeries = self.series.replace(' ', '%20')
		url = API_URL.format(tvseries=safeSeries)
		try:
			seriesData = opener.open(url).read()
			self.data = seriesData
		except:
			print 'Error retrieving JSON, contact son'
			sys.exit(1)

	def ParseAPI(self):
		"""Parses JSON data and construct EpisodeTitles dictionary with episode number and episode title."""
		jsonData = json.loads(self.data)
		season = ""
		for item in jsonData["Seasons"]:
			if item["Number"] == self.season:
				season = item
		for episode in season["Episodes"]:
			self.episodeTitles[episode["Number"]] = episode["Title"]

	def BuildDictionary(self):
		"""Compares EpisodeTitles and ParsedEpisodes dictionaries by episode number. New title is then constructed
		using the FORMAT template string. FinalTitles dictionary is then constructed using the original episode
		name from ParsedEpisodes and the new title. OS then renames files by the FinalTitles dictionary values."""
		size = len(self.parsedEpisodes)+1
		print 'New episode names:\n'
		for x in xrange(1,size):
			try:
				oldTitle = self.parsedEpisodes[x]
				filetype = oldTitle[-3:]
				name = self.episodeTitles[x]
				newTitle = FORMAT.format(show=self.series, season=self.season, episode=x, title=name, filetype=filetype)
				self.finalTitles[oldTitle] = newTitle
				print newTitle
			except KeyError:
				print 'Missing episode:', x
				pass
			
	def RenameFiles(self):
		for old, new in self.finalTitles.items():
			os.rename(old, new)
		
if __name__ == "__main__":
	if len(sys.argv) > 1:
		path = sys.argv[1]
	else:
		print 'Usage: python tvrename.py <target directory>'
		sys.exit(1)
	os.chdir(path)
	tvObj = TV(path)
	tvObj.GetEpisodes()
	tvObj.ParseEpisodes()
	tvObj.GetSeriesData()
	tvObj.ParseAPI()
	tvObj.BuildDictionary()
	r = raw_input('\nContinue with these episode titles? (Y/N): ')
	if r.lower() == 'y':
		tvObj.RenameFiles()
	else:
		sys.exit(1)